﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Threading;
using System.Diagnostics;
using UninstallHelper.Properties;
using System.Runtime.InteropServices;
using System.IO;


namespace UninstallHelper
{
    public partial class UninstallHelper : Form
    {

        public delegate void ThreadStart();
        Thread loadThread;
        ImageList imgMain;
        int iKey = 1;
        private ListViewColumnSorter lvwColumnSorter;
        Thread filterThread;
        ListView lstTemp;



        public UninstallHelper()
        {
            InitializeComponent();
        }

        private void UninstallHelper_Load(object sender, EventArgs e)
        {


            imgMain = new ImageList();
            this.refreshMenu.Enabled = false;

            lstTemp = new ListView();

            lstMain.ContextMenuStrip = contextMenuMain;

            lstMain.SmallImageList = imgMain;

            lvwColumnSorter = new ListViewColumnSorter();

            lstMain.ListViewItemSorter = lvwColumnSorter;
            lstMain.Sort();

            lvwColumnSorter.SortColumn = 0;
            lvwColumnSorter.Order = SortOrder.Ascending;

            lstMain.Sort();

            imgMain.Images.Add("0", Properties.Resources.shell32_3);

            lstMain.SetExStyles();

            lstMain.Columns[0].Width = lstMain.ClientSize.Width / 100 * 30;
            lstMain.Columns[1].Width = lstMain.ClientSize.Width / 100 * 69;

            lstMain.Update();


            loadThread = new Thread(LoadData);

            loadThread.Start();


        }


        private void LoadImages(ListViewItem lstItmen)
        {

            if (lstItmen.Tag != null)
            {

                try
                {


                    Icon lBuff = null;
                    Boolean IconSet = false;

                    if (lstItmen.Tag.ToString().Contains(".ico"))
                    {

                        string lFileName = (string)lstItmen.Tag;
                        if (lFileName.Contains(","))
                        {
                            lFileName = lFileName.Substring(0, lFileName.IndexOf(","));
                        }


                        lBuff = new Icon(lFileName);
                        IconSet = true;
                    }
                    else
                    {

                        string lFileName = (string)lstItmen.Tag;
                        if (lFileName.Contains(","))
                        {
                            lFileName = lFileName.Substring(0, lFileName.IndexOf(","));
                        }

                        IconExtractor lIcon = null;
                        try
                        {
                            lIcon = new IconExtractor(lFileName);
                        }
                        catch
                        {
                        }

                        lBuff = lIcon.GetIcon(0);
                        IconSet = true;

                    }

                    if (IconSet == false)
                    {
                        lstItmen.ImageKey = "0";
                    }
                    else
                    {
                        imgMain.Images.Add(iKey.ToString(), lBuff);
                        lstItmen.ImageKey = iKey.ToString();
                        iKey++;
                    }

                }
                catch
                {
                }

            }
            else
            {
                lstItmen.ImageKey = "0";
            }



        }


        private void UninstallHelper_Unload(object sender, EventArgs e)
        {

            if (loadThread.ThreadState == System.Threading.ThreadState.Running || loadThread.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
            {
                loadThread.Abort();
            }


        }




        private void LoadData()
        {

            //Check for 64bit System
            int bits = IntPtr.Size * 8;
            bool Is64 = bits == 64;

            if (Is64)
            {

                ListViewGroup oGroup64 = new ListViewGroup("64bit");
                ListViewGroup oGroup32 = new ListViewGroup("32bit");
                ListViewGroup oGroup64tmp = new ListViewGroup("64bit");
                ListViewGroup oGroup32tmp = new ListViewGroup("32bit");

                

                MethodInvoker group = delegate
                       {
                           lstMain.Groups.Add(oGroup64);
                           lstMain.Groups.Add(oGroup32);
                           lstTemp.Groups.Add(oGroup64tmp);
                           lstTemp.Groups.Add(oGroup32tmp);
                           lstMain.ShowGroups = true;
                       };

                Invoke(group);

                RegistryKey oKey64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
                RegistryKey oKey32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);


                RegistryKey hklmSubKeys64 = oKey64.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
                string[] lKeys64 = hklmSubKeys64.GetSubKeyNames();
                RegistryKey hklmSubKeys32 = oKey32.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
                string[] lKeys32 = hklmSubKeys32.GetSubKeyNames();


                MethodInvoker progress = delegate
                {

                    prgMain.Maximum += lKeys64.Length;
                    prgMain.Maximum += lKeys32.Length;

                };

                Invoke(progress);

                LoadDataWorker(oKey64, oGroup64);
                LoadDataWorker(oKey32, oGroup32);
                       
                

            }
            else
            {

                ListViewGroup oGroup32 = new ListViewGroup("32bit");

                MethodInvoker group = delegate
                {
                    lstMain.Groups.Add(oGroup32);
                };

                Invoke(group);

                RegistryKey oKey32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);

                RegistryKey hklmSubKeys32 = oKey32.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
                string[] lKeys32 = hklmSubKeys32.GetSubKeyNames();


                MethodInvoker progress = delegate
                {

                    prgMain.Maximum += lKeys32.Length;

                };

                Invoke(progress);
                LoadDataWorker(oKey32, oGroup32);

            }

                  
            

            MethodInvoker prgHide = delegate
            {
                refreshMenu.Enabled = true;
                prgMain.Visible = false;
                lblStatus.Text = "Alle Einträge geladen";                
            };

            Invoke(prgHide);


        }

        private void LoadDataWorker(RegistryKey baseKey, ListViewGroup oGroup)
        {

            
            RegistryKey hklmSubKeys = baseKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
            string[] lKeys = hklmSubKeys.GetSubKeyNames();

            foreach (string hklmSubKeyName in lKeys)
            {


                using (RegistryKey tempKey = hklmSubKeys.OpenSubKey(hklmSubKeyName))
                {

                    if ((string)tempKey.GetValue("DisplayName") != null)
                    {



                        MethodInvoker LabelUpdate = delegate
                        {

                            ListViewItem lNew = new ListViewItem();
                            lNew.Text = (string)tempKey.GetValue("DisplayName");

                            ListViewItem.ListViewSubItem lUString = new ListViewItem.ListViewSubItem();
                            lUString.Text = (string)tempKey.GetValue("UninstallString");

                            lNew.SubItems.Add(lUString);
                            lNew.Tag = tempKey.GetValue("DisplayIcon");

                            lNew.Group = oGroup;
                            this.lblStatus.Text = "lade Einträge...";

                            lstMain.Items.Add(lNew);

                            LoadImages(lNew);

                            lstMain.Update();
                            prgMain.Value++;



                        };

                        Invoke(LabelUpdate);
                    }
                    else
                    {
                        MethodInvoker prgUpdate = delegate
                            {
                                prgMain.Value++;
                            };

                        Invoke(prgUpdate);

                    }
                }

            }




        }


        private void beendenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        public static void ThreadProc()
        {
            Application.Run(new helpform());
        }


        private void copy_Click(object sender, EventArgs e)
        {

            if (lstMain.SelectedItems.Count > 0)
            {

                Clipboard.Clear();
                Clipboard.SetText(lstMain.SelectedItems[0].SubItems[1].Text);

            }


        }

        private void run_Click(object sender, EventArgs e)
        {


            if (lstMain.SelectedItems.Count > 0)
            {
                Process lProc = new Process();

                lProc.StartInfo.FileName = "cmd.exe";
                lProc.StartInfo.Arguments = "/C " + (string)lstMain.SelectedItems[0].SubItems[1].Text;

                lProc.Start();

            }
        }

        private void lstMain_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.lstMain.Sort();

        }

        public static void helpForm()
        {
            Application.Run(new helpform());
        }

        private void helpMenu_Click(object sender, EventArgs e)
        {
            Thread helpFormThread = new Thread(helpForm);
            helpFormThread.Start();
        }

        private void updateMenu_Click(object sender, EventArgs e)
        {

            string fileName = "Updater.exe";
            string helperPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "UninstallHelper");
            string updatePath = Path.Combine(helperPath, fileName);
            if (File.Exists(updatePath))
            {
                Process.Start(updatePath);
                Application.Exit();
            }
            else
            {
                MessageBox.Show("Die Updater Datei konnte nicht gefunden werden. Bitte verifizieren Sie, dass diese im selben Verzeichnis wie der UninstallHelper liegt.", "Updater konnte nicht gefunden werden");
            }
        }


        
        private void refreshMenu_Click(object sender, EventArgs e)
        {

            this.refreshMenu.Enabled=false;            
            this.lstMain.Items.Clear();
            this.prgMain.Visible = true;

            loadThread = new Thread(LoadData); 
            loadThread.Start();
          
        }

        private void searchBox_TextChanged(object sender, EventArgs e)
        {

            if (filterThread.ThreadState == System.Threading.ThreadState.Running || filterThread.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
            {

                filterThread.Abort(); 

            }
            else 
            {

                filterThread = new Thread(Filter);
                filterThread.Start();
            }
            

        }

        private void Filter()
        {

            



        }


    }
}
